C/C++:sizeof数组与指针

您所在的位置:网站首页 c 查看指针类型 C/C++:sizeof数组与指针

C/C++:sizeof数组与指针

2023-09-25 18:40| 来源: 网络整理| 查看: 265

C/C++:sizeof数组与指针

在C/C++中使用sizeof对数组和指针所得的结果是不一样的。

[例1]

#include #include #define SAFE_FREE(p) {free(p);p=NULL;} int main() { char arr[20]; char *p = (char *)malloc(sizeof(char) * 20); printf("sizeof arr :%d\n", sizeof(arr)); printf("sizeof p :%d\n", sizeof(p)); SAFE_FREE(p); return 0; }

输出:

[test1280@localhost 20170416]$ ./main sizeof arr :20 sizeof p :4

sizeof一个变量得到这个变量所占用的字节数。

使用sizeof对一个数组操作(sizeof是一个操作符,而不是一个函数),得到的是这个数组占用的内存字节数。

有可能会这么想:使用sizeof对一个指针操作,得到的将会是指针指向的空间所占用的字节数?

并不是!

指针是啥?指针是个变量,既然是变量,那你sizeof一个指针变量,得到的结果当然是这个指针变量占据的字节数。

一个指针变量是做什么用的?要标识一个地址,这个地址在整个计算机内是全局唯一的。

如果计算机最多寻址4G有32地址线,你用16位的一个变量能唯一标识吗?显然不可以。

一个指针变量的大小不仅和计算机本身硬件、操作系统有关,而且还和你的编译器有关系。

完全可能是在64位机上使用编译器编译出来的一个指针变量占据的大小是4字节。

注:下面所进行的所有试验都是基于以下环境:

[test1280@localhost 20170416]$ uname -a Linux localhost.localdomain 2.6.32-431.el6.i686 #1 SMP Fri Nov 22 00:26:36 UTC 2013 i686 i686 i386 GNU/Linux [test1280@localhost 20170416]$ gcc --version gcc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-18) Copyright (C) 2010 Free Software Foundation, Inc.

例1说明:

数组名和指针变量还是有区别的,虽然他们都可以通过[]或者*来访问变量/数组。

对一个指针变量用sizeof操作,得到的结果永远是指针变量本身的大小,而不是指针变量指向的空间的大小。

[例2]

#include #include #define SAFE_FREE(p) {free(p);p=NULL;} void foo(char arr[], char *p) { printf("sizeof arr :%d\n", sizeof(arr)); printf("sizeof p :%d\n", sizeof(p)); } int main() { char arr[20]; char *p = (char *)malloc(sizeof(char) * 20); foo(arr, p); SAFE_FREE(p); return 0; }

输出结果为:

[test1280@localhost 20170416]$ ./main sizeof arr :4 sizeof p :4

结论:

数组在进行函数调用作为参数被传递时,在被调用函数内部其退化为指针,使用sizeof等价于对一个指针变量进行sizeof,大小为一个指针变量所占的内存空间。

通常我们可以看到,一个形参是数组类型的,或者是指针类型的,都包含了另一个形参,是个整型值,用来标识数组类型(指针类型)的大小的,因为在被调用函数内部不知道其大小呀!

下面介绍下sizeof。

sizeof是一个操作符,而不是一个函数,其返回值是size_t类型。

sizeof是编译时进行的,也就是说,其值的大小,是在运行之前就已经决定好的,不像函数调用,是在运行期间决定的。

sizeof的对象可以是一个类型,也可以是一个变量。

#include #include int main() { printf("%d\n", sizeof(char)); printf("%d\n", sizeof(int)); char c; int i; printf("%d\n", sizeof(c)); printf("%d\n", sizeof(i)); printf("%d\n", sizeof c); printf("%d\n", sizeof i); return 0; }

编译运行都OK。

注意下面的程序:

#include #include int main() { printf("%d\n", sizeof char); printf("%d\n", sizeof int); return 0; }

编译报错:

[test1280@localhost 20170416]$ gcc -o main main.c -Wall main.c: In function ‘main’: main.c:6: error: expected expression before ‘char’ main.c:7: error: expected expression before ‘int’

总结:

使用sizeof有三种正确方式:

sizeof(type_name); sizeof(var); sizeof var;

但是sizeof type_name是错误的。

建议:

使用sizeof时,统一都加上括号吧。

[例3]

#include #include int main() { int n = 0; printf("%d\n", sizeof(n=100)); printf("%d\n", n); return 0; }

输出:

[test1280@localhost 20170416]$ !g gcc -o main main.c -Wall [test1280@localhost 20170416]$ ./main 4 0

为什么输出是0呢?关键在于,sizeof是在编译阶段就已经确定了的,表达式:

n = 100

这是一个赋值表达式,操作符=返回左操作数的类型,也就是int。

所以,在编译完成之后,运行之前,实际上就是等价于输出sizeof(int)。

由于sizeof不能被编译成机器码,所以sizeof作用范围内,也就是()里面的内容也不能被编译,而是被替换成类型。

[例4]

#include #include char char_f(){return 'a';} int int_f(){return 0;} double double_f(){return 0;} void void_f(){} int main() { printf("%d\n", sizeof(char_f())); printf("%d\n", sizeof(int_f())); printf("%d\n", sizeof(double_f())); printf("%d\n", sizeof(void_f())); printf("\n"); printf("%d\n", sizeof(void)); printf("\n"); printf("%d\n", sizeof(char_f)); printf("%d\n", sizeof(int_f)); printf("%d\n", sizeof(double_f)); printf("%d\n", sizeof(void_f)); return 0; }

输出:

[test1280@localhost 20170416]$ !g gcc -o main main.c -Wall [test1280@localhost 20170416]$ ./main 1 4 8 1 1 1 1 1 1 [test1280@localhost 20170416]$

首先前四个比较好理解,sizeof返回的是各个函数的返回值的类型的大小; 对于void来说,使用sizeof得到的是1; 末尾的四个1我暂时无法解释,留待日后解释,或者有朋友来帮我解释下~谢谢啦~ (注:函数名仅仅是个符号,代表一个地址,应该也是4,为什么是1?)

[例5]

#include #include int main() { double* (*a)[3][6]; printf("%d\n", sizeof(a)); //4 printf("%d\n", sizeof(*a)); //3*6*4 printf("%d\n", sizeof(**a)); //6*4 printf("%d\n", sizeof(***a)); //4 printf("%d\n", sizeof(****a)); //8 char arr[5][8]; printf("%d\n", sizeof(*arr)); //8 return 0; }

输出:

[test1280@localhost 20170416]$ !g gcc -o main main.c [test1280@localhost 20170416]$ ./main 4 72 24 4 8 8

对例5的解释:

a是啥?a首先是一个指针,类似于int (*a);

所以,sizeof(a)等同于sizeof(char *),也就是4(可能是8);

这个指针指向一个什么类型的数据呢? 比对int (a),指向一个int类型的数据,那么也就不难理解,这里的a指向一个double*[3][6]类型的数据;

所以*a就代表了这样的一个数据实体,里面每一个元素都是一个指针,指向一个double对象,共有这样的指针多少个呢?3*6=18个,每个指针多大呢?4字节,所以结果就是3*6*4=72;

**a从含义上来说等价于*arr;

arr是一个指向数组的指针,是数组级别的; *arr是一个指向数组中某一行的指针,是行级别的; **arr是一个指向数组中某一个元素的指针,是元素级别的。

而sizeof(arr)结果是对行所有元素求大小,即一行的元素数量每个元素的大小,所以sizeof(*arr)结果是8*1=8;

回想这里的**arr,结果自然就是6*4=24;

***arr上面已经说了,这是一个具体的对象了,这时具体的对象是一个double类型指针,所以是4(或者8);

****arr是什么类型的呢?是一个double类型,结果就是8。

基本上就是这样理解的。

额,最后来看个简单的小程序:

[例6]

#include #include #define ARRAY_SIZE(arr, type_name) (sizeof(arr)/sizeof(type_name)) int main() { char arr[] = "abcdef"; char *p = arr; printf("%d\n", sizeof(arr)); //7 printf("%d\n", sizeof(p)); //4 // 获得数组大小(以元素为单位)的方式 int array[] = {1, 2, 3, 4, 5, 6}; printf("%d\n", ARRAY_SIZE(array, int)); char s[2048] = "abcdefgh"; // 输出2048,初始化是初始化,已经确定了数组大小的情况下不会影响数组的大小,并不是9 printf("%d\n", sizeof(s)); return 0; }

输出:

[test1280@localhost 20170416]$ gcc -o main main.c [test1280@localhost 20170416]$ ./main 7 4 6 2048

值得注意的是使用一个宏来求一个数组大小的这种方式。

但是也是有前提的,必须是在可识别数组大小(sizeof 数组正确时)才是成立的,毕竟宏也仅仅是做一个替换。

参考来源:

1.http://blog.csdn.net/luguifang2011/article/details/39988627 2.http://blog.csdn.net/kangroger/article/details/20653255 3.http://www.cnblogs.com/qingergege/p/5943764.html



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3